﻿using System;
using System.Collections.Generic;
using System.Text;
using Barbar.UrlGuard.Dal.Persist;
using Barbar.UrlGuard.Dal;
using System.Net.Mail;
using System.Net;

namespace Barbar.UrlGuard.BL.Concrete {
  public class EmailAlertService : IEmailAlertService{
    private IDataContextHolder m_DataContextHolder;
    private ILogger m_Logger;

    public EmailAlertService(IDataContextHolder dataContextHolder, ILogger logger) {
      if (dataContextHolder == null)
        throw new ArgumentNullException("dataContextHolder");

      if (logger == null)
        throw new ArgumentNullException("logger");
      
      m_DataContextHolder = dataContextHolder;
      m_Logger = logger;
    }

    private SmtpClient CreateClient(EmailAlertSettings alert) {
      if (alert == null)
        throw new ArgumentNullException("alert");

      SmtpClient client = new SmtpClient(alert.SmtpServer, alert.Port);
      client.DeliveryMethod = SmtpDeliveryMethod.Network;
      if (!alert.AuthenticateSmtp) {
        client.UseDefaultCredentials = true;
      } else {
        client.UseDefaultCredentials = false;
        client.Credentials = new NetworkCredential(alert.UserName, alert.Password);
      }
      client.EnableSsl = alert.UseSsl;

      return client;
    }

    private MailMessage CreateMessageSkeleton(EmailAlertSettings alert) {
      if (alert == null)
        throw new ArgumentNullException("alert");

      MailMessage result = new MailMessage();
      result.From = new MailAddress("no-reply-urlguard@codeplex.com", "WebMonitor");
      foreach (string emailAddress in alert.Emails) {
        result.To.Add(emailAddress);
      }
      result.IsBodyHtml = false;

      return result;
    }

    public void SendEmailWarning(EmailAlertSettings alert) {
      if (alert == null)
        throw new ArgumentNullException("alert");

      SmtpClient client = CreateClient(alert);
      using (MailMessage message = CreateMessageSkeleton(alert))
      {
          List<string> invalidChains = new List<string>();
          foreach (MonitoringChain chain in m_DataContextHolder.Context.Chains)
          {
              bool isError = false;
              foreach (MonitoringEntry entry in chain.Entries)
              {
                  if (entry.LastStatusCode != 200)
                  {
                      isError = true;
                      break;
                  }
              }
              if (isError)
              {
                  invalidChains.Add(chain.Name);
              }
          }

          StringBuilder messageBuilder = new StringBuilder("Problem detected in following chains:");
          foreach (string chainName in invalidChains)
          {
              messageBuilder.AppendLine(chainName);
          }
          message.Body = messageBuilder.ToString();
          message.Subject = "Problem detected in monitored web sites";
          SafeSend(client, message);
      }
    }

    private void SafeSend(SmtpClient client, MailMessage message) {
      if (client == null)
        throw new ArgumentNullException("client");

      if (message == null)
        throw new ArgumentNullException("message");

      try {
        client.Send(message);
      } catch (SmtpException smtpException) {
        m_Logger.Fatal("Error sending alert email.", smtpException);
      }
    }

    public void SendEmailTest(EmailAlertSettings alert) {
      if (alert == null)
        throw new ArgumentNullException("alert");

      SmtpClient client = CreateClient(alert);
      using (MailMessage message = CreateMessageSkeleton(alert))
      {
          message.Body = "Congratulations from the UrlGuard team, your email settings are working !";
          message.Subject = "UrlGuard - test email";
          SafeSend(client, message);
      }
    }
  }
}
